<% ASP на блюдечке %>. Часть 7

Классический Интернет-магазин

Рубен Садоян (rouben@iname.com)

Продавцу нужен язык, покупателю — глаза.

Бенджамин Франклин

Введение

Концепция

Вариации

Что нам понадобится

Создание и подготовка базы данных

Структура нашего Интернет-магазина

Главная страничка — выбор типа заказа (файл index.asp)

Файл EquipFrameSet.html

Список категорий (Equip.asp)

Список позиций заданной категории (List.asp)

Добавление в корзину и просмотр корзины AddToCart.asp и ShowCart.asp

Сбор данных о покупателе (файл EmailOrder.asp)

Oтправка заказа по e-mail (файл Done.asp)

Еще о вариациях

   Несколько слов о поиске

   Проверка пользовательского ввода

Заключение

Введение

В частях 4 и 5 статьи «<% ASP на блюдечке %>» («Виртуальный магазин» и «Виртуальный магазин (продолжение)») читателю был предложен инструментарий, позволяющий создавать Интернет-магазины по принципу подбора составляющих (комплектующих, комплектаций, деталей, услуг и т.д.). Такой подход целесообразен во всех случаях, когда потенциального клиента интересуют возможные сочетания определенной совокупности товаров или услуг, причем с возможностью подбора подобной совокупности как самостоятельно, так и с помощью некоего «виртуального гида», интеллектуализации которого и была посвящена пятая часть статьи. И хотя такая постановка задачи охватывает достаточно широкий спектр Интернет-поставок товаров и услуг, все-таки сама концепция подбора вариантов в некотором смысле лишена универсальности. Здесь все зависит от целей, которые преследует та или иная компания, предлагающая свои товары или услуги с помощью Интернета.

В своих письмах читатели просят рассказать о реализации принципиально универсального, хотя и несколько старомодного подхода к построению Интернет-магазина. Этой теме и посвящена настоящая статья.

В начало В начало

Концепция

Концепция, изложенная в настоящей статье, хотя и несколько старомодна, однако с ее помощью можно реализовать всевозможные Интернет-магазины. Рассмотрим эту концепцию, а заодно представим реализуемую задачу поподробнее. Во-первых, это структурированная система предоставляемых товаров или услуг, реализованная в форме электронного каталога — как правило, линейной или древовидной структуры — в зависимости от степени сложности и детализованности того или иного магазина. Иными словами, это категории товаров, содержащие, в свою очередь, подкатегории и/или товары. Во-вторых, это механизм выбора определенного количества определенных товаров и их добавления в «корзину» (названную так по аналогии с обычным магазином). И наконец, в-третьих, это система регистрации заказа: отправка заказа по электронной почте, регистрация заказа в базе данных, оплата заказа по кредитной карточке и т.д. Совокупность трех этих компонентов и является по своей сути самым обычным и зачастую самым распространенным Интернет-магазином.

В начало В начало

Вариации

Существуют разнообразные вариации рассмотренной выше концепции Интернет-магазина, их огромное множество, но наиболее распространенными являются:

Известно, что из множества Интернет-магазинов особо выделяются, как правило, магазины компьютеров, бытовой техники, средств мобильной связи, медикаментов, а не продуктов питания, одежды и предметов первой необходимости. В любом случае, огромное внимание следует уделить представлению товара в Интернет-магазине, ведь покупка, к примеру, телевизора или монитора сводится не только к ознакомлению с его техническими характеристиками, но и к осмотру, «ощупыванию». Именно поэтому реализация некоторых Интернет-магазинов пока несколько затруднительна. Хотя в ряде случаев предпринимаются довольно удачные попытки воссоздания реального магазина, однако пока еще они очень далеки от совершенства.

В начало В начало

Что нам понадобится

Начнем с постановки задачи. При этом предполагается, что читатель знаком с основами ASP- и SQL-программирования — первых частей настоящей статьи для этого будет вполне достаточно.

По сути дела мы хотим организовать базу данных всего перечня товаров гипотетического магазина — магазина компьютеров и комплектующих, реализовать средства предъявления товаров, позволить покупателю выбирать и добавлять товары в корзину и посылать заказ по электронной почте.

Согласитесь, что предложенная задача весьма актуальна и на первый взгляд может показаться очень сложной, однако это не совсем так.

Для начала давайте представим себе, в чем состоит процесс покупки комплектующих, и попытаемся формализовать его. Этот процесс описывается последовательностью следующих шагов:

Как видите, последовательность выполняемых шагов по взаимодействию клиента с системой крайне проста, так что теперь можно переходить к проектированию базы данных.

В начало В начало

Создание и подготовка базы данных

Для создания базы данных (назовем ее Ishop) нам понадобится Microsoft SQL Server 7.0 или 2000. От процесса проектирования базы данных будет зависеть дальнейший объем программной логики нашего приложения, поэтому данный этап крайне ответственен. Советуем вам при проектировании Интернет-магазина стремиться к тому, чтобы ваши странички содержали как можно меньше строк и констант. Выведите все, что можно, за их пределы, вплоть до наименований позиций, так как последние могут меняться довольно часто. Иначе говоря, добейтесь, чтобы ваш код был универсальным и независимым от данных. Но поскольку принципы проектирования баз данных выходят за рамки настоящей статьи, не будем на них задерживаться и представим структуру нашей базы данных следующим образом. Создадим одну управляющую таблицу для хранения информации о наименованиях всех категорий и их соответствия таблицам с позициями, ценами и условиями гарантий (таблицу _Components), а также таблицы с перечнями позиций товаров заданных категорий.

Все таблицы создадим по одному и тому же шаблону с наименованием позиции (поле Title), розничной ценой (поле Price 1), мелкооптовой ценой (поле Price 2) и крупнооптовой ценой (поле Price 3), а также с условиями гарантии на товар (поле Description).

Далее необходимо прописать нашу базу данных в соответствующем разделе источников данных системы. Для этого сделайте следующее.

Теперь, когда база данных готова, можно приступать к созданию самого Интернет-магазина.

В начало В начало

Структура нашего Интернет-магазина

Для того чтобы было легче понять дальнейшее изложение, представим структуру нашего будущего Интернет-магазина, причем формы и действия при выборе конфигурации компьютера автоматически мы покажем синим цветом, при выборе конфигурации самостоятельно — зеленым, при выборе дополнительного оборудования — сиреневым, а начало и конец алгоритма-схемы — красным:

В предыдущих частях настоящей статьи были рассмотрены две первые ветви алгоритма-схемы. Теперь же рассмотрим подмножество алгоритма схемы, ограниченное пунктирной линией и помеченное значком «X». Как видно из схемы, в этом случае загружается набор из двух фреймов, расположенных вертикально (файл EquipFrameSet.html), причем левый фрейм загружает файл Equip.asp, а правый (основной) — файл List.asp. Затем, в зависимости от действий пользователя, производится либо добавление товаров в корзину (файл AddToCart.asp), либо просмотр корзины (файл ShowCart.asp), в любом случае ход дальнейшего «развития событий» одинаков: производится сбор информации о покупателе и отправка заказа по электронной почте.

Итак, уяснив структуру проектируемого приложения, мы можем приступить к написанию кода.

В начало В начало

Главная страничка — выбор типа заказа (файл index.asp)

Для начала создадим страничку, в которой пользователь сможет выбрать один из трех режимов дальнейшего взаимодействия с сайтом — покупку компьютера с помощью эксперта, самостоятельно или покупку дополнительного оборудования:

<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>виртуальный магазин</title>  
</head>  
   
<body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">  
<table width="780" border="0" cellspacing="0" cellpadding="0">  
<tr><td>  
   
<div align="center">  
  <p>Добро пожаловать в наш виртуальный магазин</p>  
  <p><a href="auto.asp">Подбор компьютера автоматически (с нашей помощью)</a></p>  
  <p><a href="MainForm.asp?ID=2">Подбор компьютера самостоятельно</a></p>  
  <p><a href="equipframeset.html">Покупка комплектующих</a></p>  
</div>  
   
</td></tr></table>  
   
</body>  
</html>  

Как видите, пока все просто, и параметр ID, равный 2, передается в форму MainForm.asp, где будет свидетельствовать о том, что пользователь пожелал выбрать состав компьютера самостоятельно.

В начало В начало

Файл EquipFrameSet.html

Далее, как уже было отмечено, мы будем рассматривать именно эту ветвь, то есть не случай подбора комплектующих, а случай их независимой покупки. Организуем набор фреймов для отображения перечня категорий и для организации просмотра позиций текущей категории (для простоты в настоящей статье предполагается отсутствие вложенных категорий):

<html> 
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>Виртуальный магазин</title>  
</head>  
   
<frameset cols="200,*" frameborder="NO" border="0" framespacing="0">   
  <frame name="leftFrame" scrolling="YES" noresize src="Equip.asp">  
  <frame name="MainShopFrame" src="List.asp">  
</frameset>  
<noframes>  
   
<body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">  
</body>  
</noframes>   
</html>        
В начало В начало

Список категорий (Equip.asp)

Теперь рассмотрим файл левого фрейма, содержащий список наименований категорий товаров. По сути, это набор ссылок на основной (правый) фрейм, причем организованный таким образом, что в качестве текстов самих ссылок используется наименование категории, а в качестве параметра в файл правого фрейма передается имя соответствующей таблицы базы данных. Для реализации вышеизложенного используется управляющая таблица Components:

<html> 
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>Виртуальный магазин</title>  
</head>  
   
<body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">  
   
<table width="780" border="0" cellspacing="0" cellpadding="0">  
<tr><td>  
<div align="center">  
<div align="left">  
<p><b>Комплектующие</b></p>  
<%  
 Set db = Server.CreateObject("ADODB.Connection")   
 db.Open "DSN=IShop; UID=sa;PWD=;database=Ishop"  
   
 SQLQuery = "Select * From _Components ORDER BY CategoryName ASC"  
 Set rs = db.Execute(SQLQuery)   
   
 Do While NOT rs.EOF  
   CurrentCategory = CurrentCategory + 1  
   CurTableName = rs.Fields("CategoryTableName").value  
   CategoryName = rs.Fields("CategoryName").value  
   Response.Write "<a href='List.asp?TName=" & CurTableName &_  
                             "' class='antiLine' target='MainShopFrame'>" & CategoryName & "</a><br>"  
   rs.MoveNext  
 Loop  
   
 db.Close  
 Set db = Nothing  
%>  
   
</div>  
   
</td></tr></table></div>  
</body>  
</html>

Как видите, производится подключение к базе данных и выполняется выборка из таблицы _Components. Затем в цикле динамически формируются ссылки на файл List.asp с параметрами, которые в дальнейшем будут использованы для построения запроса к необходимой таблице данных - в зависимости от категории товаров, выбираемой пользователем при переходе по соответствующей ссылке.

В начало В начало

Список позиций заданной категории (List.asp)

Теперь надлежит организовать просмотр списка позиций товаров заданной категории и предоставить пользователю механизм добавления в корзину заданного количества единиц товара. Здесь прежде всего необходимо уяснить для себя понятие «корзина» и уточнить порядок взаимодействия с ней.

Итак, с точки зрения пользователей корзина должна представлять собой окно с перечнем добавленных товаров или услуг, с указанием их цены и добавленного количества. В некоторых случаях необходима и возможность редактирования этого перечня. С точки же зрения разработчиков, то есть нас с вами, корзина - это определенная область памяти, в которой должна храниться информация о сделанных заказах, причем эта область памяти - сессионная, то есть обнуляется при открытии новой сессии.

Вообще говоря, возможны два подхода к созданию корзины: с использованием сессионных переменных и с использованием «ключиков» (cookies). Каждый из этих механизмов имеет свои преимущества и недостатки. Так, достоинство первого механизма заключается в большей гибкости (большем числе возможностей) и большей защищенности (сессионные переменные недоступны для клиента), а второй механизм, в отличие от первого, хранит информацию в браузере клиента, что разгружает канал передачи данных от сервера к клиенту.

В нашем случае мы используем механизм сессионных переменных, то есть в качестве области хранения информации о заказе будут использоваться переменные, принадлежащие сессии нашего Web-приложения:

<html> 
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>Виртуальный магазин</title>  
</head>  
   
' Сформируем ссылку на файл, организующий показ корзины, и будем передавать   
' в него параметр, определяющий сбрасывание содержимого корзины.  
   
<a href="javascript:op('ShowCart.asp?Clear=1')">Ваша корзина</a>&nbsp;&nbsp;&nbsp;&nbsp;  
   
<%  
 CartItems = Session ("CartItems")  
' Прочитаем количество пунктов, добавленных в корзину из сессионной переменной CartItems  
   
 Height = CInt(CartItems) * 20 + 150  
' Вычислим высоту генерируемого окна корзины и установим ограничение на ее значение   
   
 If (Height >= 600) Then Height = 600 End if  
   
 If (CartItems = 0) Then  
  Response. Write "Ваша корзина пуста."  
 Else  
  Response.Write "Всего в корзине " & CartItems  
  If (CartItems = 1) Then Response. Write " позиция" End If  
  If (CartItems = 2 OR CartItems = 3 OR CartItems = 4) Then Response. Write " позиции" End If  
  If (CartItems >= 5) Then Response. Write " позиций" End If  
 End If  
%>  
   
<Script>  
   
<%  
 ' Генерация JavaScript функции показа корзины (передаем в качестве параметра высоту окна)  
 Response.Write "function op(URL)"  
 Response.Write "{var wnd=open(URL,'','resizable=1,toolbar=0,directories=0,statusbar=0,width=720,height="  
 Response.Write CStr(Height) & "');}"  
%>  
   
</Script>  
   
<body bgcolor="#D7D5C0" text="#000000" link="#000000" vlink="#FFFFFF" alink="#FFFFFF">  
<form method="get" name= "MainForm" action="AddToCart.asp">  
   
<table width="780" border="0" cellspacing="0" cellpadding="0">  
<tr><td>  
<div align="left">  
   
<table width="620" border="2" cellspacing="0" cellpadding="0">  
<tr>  
 <td width="465"><b><center>Позиция</center></b></td>  
 <td width="16"><b><center>Цена</b></center></td>  
 <td width="46"><b><center>Кол-во</b></center></td>  
 <td width="20"><b><center>+</b></center></td>    
</tr>  
   
<%  
' Прочитаем имя таблицы данных из предыдущей формы   
' и обновим значение соответствующей сессионной переменной  
 TableName = Request.QueryString("TName")  
 Session ("TName") = TableName  
   
'Осуществим подключение к базе данных и выполним запрос к указанной таблице данных  
 Set db = Server.CreateObject("ADODB.Connection")   
 db.Open "DSN=IShop; UID=sa;PWD=;database=Ishop"  
   
' Если имя таблицы не пусто, организуем цикл показа позиций  
 If TableName <> "" Then  
  SQLQuery = "Select * From " & TableName & " WHERE Title <> 'Выберите позицию' ORDER BY Title ASC"  
  Set rs = db.Execute(SQLQuery)   
   
  CurrentCategory = 1  
   
  Do While NOT rs.EOF  
   Response.Write "<tr><td>" & rs.Fields("Title").value & "</td>"  
   Response.Write "<input type='hidden' name='Title" & CurrentCategory & _  
"' value='" & rs.Fields("Title").value & "'>"   
   Response.Write "<td>" & rs.Fields("Price1").value & "</td><td>"  
   
  'Определим текстовое поле для ввода значений количества единиц товара  
  ' и кнопку, осуществляющую добавление товаров в корзину (переход к следующей форме)  
   Response.Write "<input id = 'quantity'" & CurrentCategory & " type='text' name='quant" &_  
 CurrentCategory & "' maxlength='5' size='5'>"   
   Response.Write "</td><td>"  
   Response.Write "<INPUT type='submit' value='+' name=submit></td></tr>"  
   rs.MoveNext  
   CurrentCategory = CurrentCategory + 1  
  Loop  
   
  Response.Write "</table><br>"  
   
  db.Close  
  Set db = Nothing  
   
 Else  
End If  
%>  
<br>  
   
</form>  
</body>  
</html>  

Обратите внимание на то, что в цикле по результатам выполнения выборки всех записей таблицы заданной категории, по сути, выполняется генерация кнопок типа Submit, выполняющих загрузку странички-действия (указанной атрибутом action формы), в данном случае - странички добавления позиции в корзину AddToCart.asp.

В начало В начало

Добавление в корзину и просмотр корзины AddToCart.asp и ShowCart.asp

Как было сказано выше, при добавлении позиций в корзину (при нажатии на кнопку «+») производится передача управления файлу AddToCart.asp:

<head>  
<title>Ваша корзина</title>  
</head>  
   
<%  
  ClearAll = 0  
   
 'Организация опроса кнопок корзины   
  CurAction = Request.QueryString("Submit")  
   
  If (CurAction = "Очистить корзину") Then  
    Session ("Cart") = ""  
    Session ("CartItems") = 0  
    Session ("Sum") = 0  
    ClearAll = 1  
  End If  
   
  If (CurAction = "Оформить заказ") Then  
    Response.Redirect "EmailOrder.asp?IsCart=1"  
  End If  
   
 ' Считывание сессионной переменной с именем таблицы данных  
  TableName = Session("TName")  
    
 ' Организация подключения к базе данных и выборка значений  
  Set db = Server.CreateObject("ADODB.Connection")   
  db.Open "DSN=IShop; UID=sa;PWD=;database=Ishop"  
   
 If TableName <> "" Then  
  SQLQuery = "Select * From " & TableName & " WHERE Title <> 'Выберите позицию' ORDER BY Title ASC"  
  Set rs = db.Execute(SQLQuery)   
   
  CurrentCategory = 1  
  CurCart = ""  
  Sum = Session ("Sum")  
  CartItems = CInt(Session ("CartItems"))  
       
  If (ClearAll <> 1) Then  
   ' Формирование строки с компонентами корзины для тех записей таблицы,  
   '  соответствующие которым значения количества товара не равны 0  
   Do While NOT rs.EOF  
    Str = "quant" & CStr(CurrentCategory)  
    CurQuant = Request.QueryString(Str)  
   
    If Not IsNumeric(CurQuant) Then  
     Response.Write "Ошибка указания единиц позиции."  
    Else  
   
    If (CurQuant <> "0" AND CurQuant <> "") Then  
     CurCart = "<tr><td>" & rs.Fields("Title").value & "</td>"  
     CurCart = CurCart & "<td>" & rs.Fields("Price1").value & "</td><td>"  
     CurCart = CurCart & CStr(CurQuant) & "</td><td>"  
     Total = CInt(CurQuant) * rs.Fields("Price1").value  
     Sum = Sum + Total  
     CurCart = CurCart & CStr(Total) & "</td></tr>"  
     CartItems = CartItems + 1  
    End If  
   End If  
   
    rs.MoveNext  
    CurrentCategory = CurrentCategory + 1  
   Loop  
   
   ' Обновление сессионных переменных  
   ' CartItems – количество элементов корзины  
   ' CartVal – HTML-представление элементов корзины, то есть значение корзины  
   ' Sum – итоговая сумма цен элементов корзины  
   
   Session ("CartItems") = CartItems  
   CartVal = Session ("Cart")  
   Session ("Cart") = CartVal & CurCart  
   CartVal = Session ("Cart")  
   Session ("Sum") = Sum  
   
  End IF  
   
 End If  
 db.Close  
 Set db = Nothing  
   
 Response.Redirect "List.asp?TName=" & Session ("TName")  
' Безусловный переход к файлу List.asp с параметром (именем таблицы данных)  
%>  

Следует обратить особое внимание на последнюю строку:

Response.Redirect "List.asp?TName=" & Session ("TName")  

По сути, осуществляется не переход, а возврат к страничке List.asp. Если же принять во внимание то обстоятельство, что текущая страничка (AddToCart.asp) никаких видимых (заметных для пользователя) действий (кроме добавления позиций в соответствующую сессионную переменную) не производит, то с точки зрения пользователя ровным счетом ничего не происходит.

Обратите внимание также и на то, каким образом производится обработка нажатий на кнопки «Очистить корзину» и «Оформить заказ». Будучи кнопками типа submit-формы, реализованной на страничке ShowCart.asp (см. об этом ниже), они возвращают определенные значения (которые мы зададим впоследствии), что мы и используем для обнуления корзины (сессионных переменных, хранящих содержимое корзины) и оформления заказа (безусловной передачи управления страничке EmailOrder.asp).

Как видите, сама сессионная переменная, содержащая добавленные в корзину позиции, представляет собой простую совокупность последовательно прибавляемых строк с необходимыми данными, заключенными в тэги таблицы. Конечно, это далеко не самый лучший способ организации хранения данных в корзине (в частности, он не позволяет осуществлять редактирование ее содержимого), но тем не менее в определенных случаях разработчики довольствуются и им.

Файл ShowCart.asp отличается от файла AddToCart.asp лишь тем, что вместо осуществления конкатенации (добавления) к сессионной переменной содержимого корзины, он попросто организует показ этого содержимого в новом окне:

…
   Do While NOT rs.EOF  
    Str = "quant" & CStr(CurrentCategory)  
    CurQuant = Request.QueryString(Str)  
   
    If (CurQuant <> "0" AND CurQuant <> "") Then  
     CurCart = "<tr><td>" & rs.Fields("Title").value & "</td>"  
     CurCart = CurCart & "<td>" & rs.Fields("Price1").value & "</td><td>"  
     CurCart = CurCart & CStr(CurQuant) & "</td><td>"  
     Total = CInt(CurQuant) * rs.Fields("Price1").value  
     Sum = Sum + Total  
     CurCart = CurCart & CStr(Total) & "</td></tr>"  
    End If  
   
    rs.MoveNext  
    CurrentCategory = CurrentCategory + 1  
   Loop  
   
   CartVal = Session ("Cart")  
   Session ("Cart") = CartVal & CurCart  
   CartVal = Session ("Cart")  
   Session ("Sum") = Sum  
   
   Response.Write CartVal  
…

Последняя строка приведенного фрагмента исходного текста и осуществляет вывод содержимого корзины на экран.

В результате получится система, состоящая из списка категорий, списка позиций выбранной категории и корзины (см. рисунок).

В начало В начало

Сбор данных о покупателе (файл EmailOrder.asp)

Далее следует обычная страничка сбора информации о пользователе:

<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
</head>  
   
<body bgcolor="#006767" text="#FFFFFF" link="#FFFF00" vlink="#FFFF00">  
<div align="center">  
   
<p>Отправка заказа по электронной почте:</p>  
   
<p>Как с Вами связаться</p>  
   
<Form Method="get" Action = "Done.asp">  
<table>  
<tr>  
<td>Ваше имя:</td>  
<td><Input Type="text" Name="Name" Size="30"></Input></td>  
</tr>  
   
<tr>  
<td>Ваш телефон:</td>  
<td><Input Type="text" Name="Phone" Size="30"></Input></td>  
</tr>  
   
<tr>  
<td>Ваш адрес:</td>  
<td><Input Type="text" Name="Address" Size="30"></Input></td>  
</tr>  
   
<tr>  
<td>Ваш электронный адрес:</td>  
<td><Input Type="text" Name="Email" Size="30"></Input></td>  
</tr>  
   
<tr>  
<td>Ваш UIN:</td>  
<td><Input Type="text" Name="UIN" Size="30"></Input></td>  
</tr>  
   
<tr>  
<td align = center><Input Type="submit" Value="Отправить заказ"></Input></td>  
</tr>  
   
</table>  
   
<%  
 I = 1  
   
 Do While I <= 15  
   
 ' Прочитаем в цикле значения скрытых полей «select#»  
 '  и сгенерируем скрытые элементы формы  
 ' для передачи выбранных значений в последующие скрипты  
   
  Str = "select"  
  Str = Str & CStr(I)  
  Res = Request.QueryString(Str)  
  Response.Write "<input type='hidden' name='" & Str & "' value='" & Res & "'>"   
   
 ' Прочитаем в цикле значения скрытых полей «quant#»  
 '  и сгенерируем скрытые элементы формы  
 ' для передачи выбранных значений в последующие скрипты  
   
  Str = " quant"  
  Str = Str & CStr(I)  
  Res = Request.QueryString(Str)  
  Response.Write "<input type='hidden' name='" & Str & "' value='" & Res & "'>"   
   
 ' Прочитаем в цикле значения скрытых полей «price#»  
 '  и сгенерируем скрытые элементы формы  
 ' для передачи выбранных значений в последующие скрипты  
   
  Str = "price"  
  Str = Str & CStr(I)  
  Res = Request.QueryString(Str)  
  Response.Write "<input type='hidden' name='" & Str & "' value='" & Res & "'>"   
   
  I = I + 1  
 Loop  
   
' Если на страничку пришли из корзины, то заведем скрытое поле  
' и придадим ему соответствующее значение  
   
If (Request.QueryString("IsCart") = 1) Then  
  Response.Write "<input type='hidden' name='Cart' value='1'>"   
End If  
   
%>  
   
</Form>  
<br>  
</div>  
</body>  
</html>  
В начало В начало

Oтправка заказа по e-mail (файл Done.asp)

После того как все действия выполнены успешно, необходимо сформировать электронное письмо, которое одновременно должно быть послано как гипотетическому менеджеру по продажам или доставке нашего виртуального магазина, так и самому пользователю в подтверждение выполненного заказа. Для этого воспользуемся стандартной ActiveX компонентой CDONTS:

<html> 
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>Виртуальный магазин</title>  
</head>  
   
<body bgcolor="#006767" text="#FFFFFF" link="#FFFF00" vlink="#FFFF00">  
<table width="780" border="0" cellspacing="0" cellpadding="0">  
<tr><td>  
<div align="center">  
   
<%  
 Name = Request.QueryString("Name")  
 Phone = Request.QueryString("Phone")  
 Address = Request.QueryString("Address")  
 Email = Request.QueryString("Email")  
 UIN = Request.QueryString("UIN")  
   
 Dim myMail   
 Set myMail = CreateObject("CDONTS.NewMail")   
   
 myMail.From = Email   
 myMail.To = "rouben@iname.com"   
 myMail.Subject = "Order from" & Name  
   
 Body = Body & "Уважаемый " & Name & "!" & CHR(13) & CHR(10)   
 Body = Body & "Имя: " & Name & CHR(13) & CHR(10)  
 Body = Body & "Телефон: " & Phone & CHR(13) & CHR(10)  
 Body = Body & "Адрес: " & Address & CHR(13) & CHR(10)  
 Body = Body & "E-mail: " & Email & CHR(13) & CHR(10)  
 Body = Body & "UIN: " & UIN & CHR(13) & CHR(10) & CHR(13) & CHR(10)  
 Body = Body & "Вы заказали:"  
   
 I = 1  
 Total = CDbl(0)  
   
 ComponentCount = Session("ComponentCount")  
   
 'Если это не корзина, то будем осуществлять обработку обычным способом  
 If (Request.QueryString ("Cart") <> 1) Then  
   
  Do While I <= ComponentCount  
   Body = Body & CHR(13) & CHR(10) & I & ". "  
   Str = "select"  
   Str = Str & CStr(I)  
   Res = Request.QueryString(Str)  
   Body = Body & " - " & Res & " - "  
   Str = "quant"  
   Str = Str & CStr(I)  
   Res1 = Request.QueryString(Str)  
   Body = Body & Res1 & " - "  
   I = I + 1  
  Loop  
   
' В противном случае произведем добавление к телу электронного письма   
' сессионной переменной с содержимым корзины  
 Else  
   CartVal = Session ("Cart")  
   Body = Body & CartVal  
 End If  
   
 D = Date()  
 D = FormatDateTime(D,1)  
   
 Body = Body & CHR(13) & CHR(10)  
 Body = Body & "Отправленно:" & D  
 Body = Body & CHR(13) & CHR(10)  
   
 Body = Body & "Итого с Вас: " & Total & " у.е." & CHR(13) & CHR(10) & CHR(13) & CHR(10)  
 Body = Body & "Наши менеджеры свяжутся с Вами в ближайшее время по оставленным Вами координатам."  
 Body = Body & CHR(13) & CHR(10) & "С наилучшими пожеланиями" & CHR(13) & CHR(10)  
 Body = Body & "Сервер 'Виртуального магазина'"  
   
 myMail.Body = Body   
 'Response.Write Body  
   
 On Error Resume Next  
  myMail.Send   
 If Err <> 0 Then  
   Response.Write "Error encountered: " & Err.Description  
 End If  
   
 Response.Write "<center><p>Уважаемый " & Name & "!<br>"  
 Response.Write "Ваш заказ был успешно отправлен на сервер Виртуального магазина.<br>"  
 Response.Write "Спасибо!</p></center>"  
%>   
   
</div>  
   
</td></tr></table>  
   
</body>  
</html>
В начало В начало

Еще о вариациях

Несколько слов о поиске

Разумеется, ни один мало-мальски солидный Интернет-магазин не обходится без такого важного инструментария, как поиск позиций. Здесь возникает целая куча вопросов о том, что, где, как и по каким критериям искать. Скажем сразу, что однозначно ответить на все эти вопросы невозможно, поскольку это зависит от специфики поставляемых товаров или услуг и «заточено» под конкретные коммерческие цели, преследуемые теми или иными организаторами Интернет-торговли. Однако осмелимся предложить возможное решение, основанное с инструментальной точки зрения на результатах просмотра многочисленных Интернет-магазинов самого широкого спектра товаров. Для простоты дальнейшего изложения рассмотрим пример, связанный с нашим магазином.

Прежде всего необходимо организовать форму поиска по ключевым словам (по подстроке) в наименованиях позиций, причем как по всем категориям (по всей базе данных), так и по заданной (следовательно, нужно предусмотреть компонент выбора категории поиска). Кроме того, стоит предусмотреть возможность поиска товаров и по ценовым критериям, например искать все товары, цена которых меньше определенного заданного значения. Совокупность этих критериев и будет определять результаты поиска. Итак, для начала создадим форму поиска, удовлетворяющую описанным выше критериям (см. рисунок):

Как видите, форма попросту добавлена в файл страницы списка позиций заданной категории List.asp. Сделано это простым добавлением строки в начало файла List.asp:

<!--#include file="SearchForm.asp" -->

Сама же форма (как явствует из ссылки на соответствующий файл) представлена в файле SearchForm.asp следующим образом:

<html>  
<head>  
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">  
<title>Виртуальный магазин</title>  
</head>  
   
<body bgcolor="#006767" text="#FFFFFF" link="#FFFF00" vlink="#FFFF00">  
   
<%  
  Set db = Server.CreateObject("ADODB.Connection")  
  db.Open "DSN=ISHop; UID=sa;PWD=;database= ISHop"  
   
  SQLQuery = "SELECT * FROM _Components ORDER BY CategoryName ASC"  
  Set rs = db.Execute(SQLQuery)   
%>  
   
<form name="SearchForm" method="get" action="Search.asp">  
 <p> Искать:   
   <input type="text" name="SearchString" size="15" maxlength="15">  
    в категории:   
    <select style="WIDTH: 140px" name="CategorySel">  
      <option value="AllCategories">Во всех</option>  
<%  
      Do While NOT rs.EOF  
       Response.Write "<option value='" & rs.Fields("CategoryTableName").value & _  
                                 "'>" & rs.Fields("CategoryName").value & "</option>"  
       rs.MoveNext  
     Loop  
%>  
</select>  
 цена:   
    <select name="BounderSel">  
      <option value="AnyPrice"></option>  
      <option value="&lt;=">&lt;=</option>  
      <option value="&gt;=">&gt;=</option>  
    </select>  
    <input type="text" name="PriceBound" size="3" maxlength="4">  
    <input type="submit" name="Submit" value="Поиск">  
  </p>  
</form>  
   
<%  
 db.Close  
 Set db = Nothing  
%>  
   
</body>  
</html>  

Здесь в качестве обработчика формы указана страничка Search.asp, по сути являющаяся модификацией файла List.asp для случая формирования списка позиций не из одной, а из нескольких таблиц, согласно введенным критериям запроса. Приведем фрагмент кода странички Search.asp, отвечающий за формирование запросов к базе данных, исходя из состояния полей нашей поисковой формы:

<% 
…  
 SearchString = Request.QueryString("SearchString")  
 CategorySel  = Request.QueryString("CategorySel")  
BounderSel   = Request.QueryString("BounderSel")  
PriceBound   = Request.QueryString("PriceBound")  
…  
 If SearchString = "" Then  
     If (BounderSel = "AnyPrice" OR PriceBound = "" ) Then  
        SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию' ORDER BY Title ASC"  
     Else  
        SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию'" &_  
                   " AND Price1 " & BounderSel & PriceBound & " ORDER BY Title ASC"  
     End If  
    Else  
      If (BounderSel = "AnyPrice" OR PriceBound = "" ) Then  
        SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию'" &_  
                             " AND Title LIKE '%" & SearchString & "%' ORDER BY Title ASC"  
      Else  
        SQLQuery = "Select * From " & TN & " WHERE Title <> 'Выберите позицию'” &_  
                             ” AND Title LIKE '%" & SearchString & _  
                            "%' AND Price1 " & BounderSel & PriceBound & " ORDER BY Title ASC"  
      End If  
    End If  
…  
%>  

Как видите, после считывания значений полей нашего поискового компонента в переменные, производится анализ пользовательского ввода и формируется строка запроса к базе данных исходя из введенных значений.

Единственным существенным отличием от файла и странички List.asp является то, что поиск может быть осуществлен по всем таблицам данных, для этого:

<% 
…  
'Если пользователь запустил поиск по всем категориям, т.е. таблицам  
   
     If (CategorySel = "AllCategories") Then  
       SQLQuery = "Select * From _Components"  
       Set res = db.Execute(SQLQuery)   
   
       Do While NOT res.EOF  
         CurTableName = res.Fields("CategoryTableName").value  
         'Функция показа содержимого текущей таблицы  
         FetchFromTable CurTableName   
         res.MoveNext  
       Loop  
   
     'В противном случае (поиск только по одной таблице)  
     Else  
       FetchFromTable CategorySel  
     End If  
…  
%>  

Таким образом, сделав несколько изменений и слегка переработав страничку показа списка позиций заданной категории List.asp, можно получить страничку вывода результатов поиска Search.asp (предлагаем вам проделать это самостоятельно).

В начало В начало

Проверка пользовательского ввода

В завершение хотелось бы рассмотреть несколько полезных JavaScript-сценариев для проверки корректности ввода информации о пользователе и всевозможных типов данных. В связи с тем, что наблюдается определенный дефицит таких функций, была разработана библиотека сценариев, использование которых позволило облегчить задачу обработки пользовательского ввода. Для удобства все функции сгруппированы в один файл (script.js):

… 
Проверка целого значения
…  
   
function isInteger (s,message){  
// s is a string  
// message  – строка с сообщением об ошибке  
   
var i;  
   
for (i = 0; i < s.length; i++){     
 // Убедимся, что текущий символ является цифрой  
 var c = s.charAt(i);  
 if (!isDigit(c)) {  
 alert(message);                                   
 return false;  
}  
}  
return true;  
}  
   
…  
Проверка цифры  
…  
function isDigit (c) {  
// c – символ  
 return ((c >= "0") && (c <= "9"))  
}  
   
…  
Преобразование строки в число с отбрасыванием посторонних символов  
…  
function numericize(s) {  
// s – строка  
// message  – строка с сообщением об ошибке  
   
var i,j;  
j="";  
   
for (i=0;i<s.length;i++) {  
 if (isDigit(s.charAt(i))){  
   j=j+s.charAt(i);  
}  
}  
return j;  
}  
   
…  
Проверка «пустоты» введенного значения  
…  
function isBlank (s,message) {  
// s – рассматриваемый элемент формы  
// message  – строка с сообщением об ошибке  
   
if ((s.value.length > 0) && (s.value != null) && (s.value != "")){  
 return false;  
}  
alert(message);  
s.focus();  
return true;  
}  
   
…  
Проверка номера телефона  
…  
function isPhone (s,message) {  
// s – рассматриваемый элемент формы  
// message  – строка с сообщением об ошибке  
// Удалим символы, не являющиеся цифрами, и вычислим длину полученной строки  
   
if (s.value.length > 10) {  
 s.value = numericize(s.value);  
}  
                  
//По крайней мере 3 цифры – код города и 7 цифр — номер телефона  
if (s.value.length == 10) {  
if (isInteger(s.value,message)) {  
 return true;  
}  
else {  
 s.focus();  
 return false;  
}  
}  
else {   
 alert(message);  
 s.focus();  
 return false;  
 }  
return true;  
}  
   
…  
Проверка адреса электронной почты 
…  
function isEmail (s,message) {  
// s – рассматриваемый элемент формы  
// message  – строка с сообщением об ошибке  
   
var i,ii;  
var j;  
var k,kk;  
 var jj;  
 var len;  
      
 // Пусто?  
   
if (isBlank(s,message)) {  
 s.focus();  
 return false;  
}  
   
 // Проверка адреса электронной почты  
 // Адрес должен содержать "@" и "."  
 // В строке адреса должен быть хотя бы 1 символ до символа "@"  
 // После символа "@" и перед символом "." должен быть хотя бы 1 символ  
 // после символа  "." должно быть по крайней мере еще 2 символа  
   
 if (s.value.length >0) {  
 i =s.value.indexOf ("@");  
 ii=s.value.indexOf ("@",i+1);  
 j=s.value.indexOf (".",i);  
 k=s.value.indexOf (",");  
 kk=s.value.indexOf (" ");  
 jj=s.value.lastIndexOf (".")+1;  
 len=s.value.length;  
   
 if ((i>0) && (j>(1+1)) && (k==-1) && (ii==-1) && (kk==-1) &&  
     (len-jj >=2) && (len-jj<=3)) {}  
else {  
 alert(message)  
 s.focus();                                               
 return false;  
}  
}  
 return true;  
}  
   
…  
Проверка выбора значения из списка  
…  
function isSelected (s,message) {  
// s – рассматриваемый элемент формы  
// message  – строка с сообщением об ошибке  
// Проверяет список выбора на предмет изменения его значения   
// по сравнению со значением, задаваемым по умолчанию  
   
if (s.selectedIndex==0) {  
 alert(message);  
 s.focus();  
 return false;  
}  
return true;  
}  

Использовать данный файл крайне просто. Для этого в тэге объявления формы в качестве скрипта проверки необходимо указать определенную функцию, например:

…  
<Form Name="MainForm" ACTION="Process.asp" Method=Post onSubmit="return PreProcess();">  
…  

Далее следует включить вышеприведенный файл с библиотекой функций в разрабатываемое Web-приложение:

…  
<Script Type = "text/javascript" Src = "script.js">  
<!--  
 // В случае, если библиотека не найдена  
 document.write ("Библиотека JavaScript не найдена.");  
//-->  
</Script>  
…  

Определить функцию проверки, которая и будет осуществлять вызов необходимых функций нашей библиотеки:

<Script Tupe = "text/javascript"> 
   
function PreProcess()   
{  
 var ok;  
 with (document.MainForm) {  
   
  // Пусто ли имя  
   if (isBlank(name,'Введите имя.')) {  
return false;  
  }  
   
// Проверка номера домашнего телефона  
  if (!isPhone (homephone,'Введите корректный номер домашнего телефона.')) {  
   return false;  
 }  
   
// Проверка адреса электронной почты  
if (!isEmail (email,'Пожалуйста, введите корректный адрес электронной почты.')) {  
  return false;  
}  
   
}  
return true;  
}  
</Script>
В начало В начало

Заключение

Как уже неоднократно было сказано выше, Интернет-магазинов великое множество. И если раньше они считались всего лишь игрушками, не позволяющими реально осуществлять ежедневные покупки всевозможных товаров, то теперь это серьезные системы, за которыми стоят не менее серьезные организации, профессионально занимающиеся бизнесом. В последнее время понятие Интернет-торговли перестало быть чем-то экзотическим, а возможность приобрести практически любой товар, не вставая из-за компьютера, стала поистине огромной.

Прежде чем приступать к созданию своего Интернет-магазина, советуем для начала «побродить»по чужим. Для ориентации читателей в мире отечественных Интернет-магазинов приведем список наиболее привлекательных из них:

MEGAShop - магазин компьютерной техники http://www.megashop.ru/index14.html

Kenga - магазин детских товаров и игрушек http://www.kenga.ru/toys_main.php3

24x7 - книги, видео, музыка, игрушки http://www.24x7.ru/

Каталог книжных магазинов зоны .ru http://www.findbook.h1.ru/

Korzina.ru - российская сеть магазинов с доставкой http://www.korzina.ru/

WebMarket.ru - http://www.webmarket.ru/

Торговый город - http://www.delo.omsknet.ru/shop/

Электронный торговый дом AVT - http://www.avt.ru/etd.shtml/

 

Полный архив исходных текстов ASP-страниц к настоящей статье лежит здесь.

КомпьютерПресс 4'2001